home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / ASSEMBLE / 1586.ZIP / ASM-SRC.ARC / MOVEM.C < prev    next >
Text File  |  1988-09-05  |  9KB  |  336 lines

  1. /***********************************************************************
  2.  *
  3.  *        MOVEM.C
  4.  *        Routines for the MOVEM instruction and the REG directive
  5.  *
  6.  *    Function: movem()
  7.  *        Builds MOVEM instructions. The size of the instruction
  8.  *        is given by the size argument (assumed to be word if 
  9.  *        not specified). The label argument points to the label 
  10.  *        appearing on the source line containing the MOVEM 
  11.  *        instruction, if any, and the op argument points to the
  12.  *        operands of the MOVEM instruction. The routine returns
  13.  *        an error code in *errorPtr by the standard mechanism. 
  14.  *
  15.  *        reg()
  16.  *        Defines a special register list symbol to be used as an
  17.  *        argument for the MOVEM instruction. The size argument
  18.  *        reflects the size code appended to the REG directive,
  19.  *        which should be empty. The label argument points to the
  20.  *        label appearing on the source line containing the REG
  21.  *        directive (which must be specified), and the op
  22.  *        argument points to a register list which is the new
  23.  *        value of the symbol. The routine returns an error code
  24.  *        in *errorPtr by the standard mechanism. 
  25.  *
  26.  *     Usage:    movem(size, label, op, errorPtr)
  27.  *        int size;
  28.  *        char *label, *op;
  29.  *        int *errorPtr;
  30.  *
  31.  *        reg(size, label, op, errorPtr)
  32.  *        int size;
  33.  *        char *label, *op;
  34.  *        int *errorPtr;
  35.  *
  36.  *      Author: Paul McKee
  37.  *        ECE492    North Carolina State University
  38.  *
  39.  *        Date:    12/9/86
  40.  *
  41.  ************************************************************************/
  42.  
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include "asm.h"
  47.  
  48.  
  49. /* Define bit masks for the legal addressing modes of MOVEM */
  50.  
  51. #define ControlAlt  (AnInd | AnIndDisp | AnIndIndex | AbsShort | AbsLong)
  52. #define DestModes   (ControlAlt | AnIndPre)
  53. #define SourceModes (ControlAlt | AnIndPost | PCDisp | PCIndex)
  54.  
  55.  
  56. extern long    loc;
  57. extern char pass2;
  58.  
  59.  
  60.  
  61. int    movem(size, label, op, errorPtr)
  62. int    size;
  63. char    *label, *op;
  64. int    *errorPtr;
  65. {
  66. char *p, *opParse();
  67. int status;
  68. unsigned short regList, temp, instMask;
  69. char i;
  70. opDescriptor memOp;
  71.  
  72.     /* Pick mask according to size code (only .W and .L are valid) */
  73.     if (size == WORD)
  74.         instMask = 0x4880;
  75.     else if (size == LONG)
  76.         instMask = 0x48C0;
  77.     else {
  78.         if (size)
  79.             NEWERROR(*errorPtr, INV_SIZE_CODE);
  80.         instMask = 0x4880;
  81.         }
  82.     /* Define the label attached to this instruction */
  83.     if (*label)
  84.         define(label, loc, pass2, errorPtr);
  85.  
  86.     /* See if the instruction is of the form MOVEM <reg_list>,<ea> */
  87.     status = OK;
  88.     /* Parse the register list */
  89.     p = evalList(op, ®List, &status);
  90.     if (status == OK && *p == ',') {
  91.         /* Parse the memory address */
  92.         p = opParse(++p, &memOp, &status);
  93.         NEWERROR(*errorPtr, status);
  94.         if (status < ERROR) {
  95.             /* Check legality of addressing mode */
  96.             if (memOp.mode & DestModes) {
  97.                 /* It's good, now generate the instruction */
  98.                 if (pass2) {
  99.                     output((long int) (instMask | effAddr(&memOp)), WORD);
  100.                     loc += 2;
  101.                     /* If the addressing mode is address
  102.                        register indirect with predecrement,
  103.                        reverse the bits in the register 
  104.                        list mask */
  105.                     if (memOp.mode == AnIndPre) {
  106.                         temp = regList;
  107.                         regList = 0;
  108.                         for (i = 0; i < 16; i++) {
  109.                             regList <<= 1;
  110.                             regList |= (temp & 1);
  111.                             temp >>= 1;
  112.                             }
  113.                         }
  114.                     output((long) regList, WORD);
  115.                     loc += 2;
  116.                     }
  117.                 else
  118.                     loc += 4;
  119.                 extWords(&memOp, size, errorPtr);
  120.                 return NORMAL;
  121.                 }
  122.             else {
  123.                 NEWERROR(*errorPtr, INV_ADDR_MODE);
  124.                 return NORMAL;
  125.                 }
  126.             }
  127.         }
  128.  
  129.     /* See if the instruction is of the form MOVEM <ea>,<reg_list> */
  130.     status = OK;    
  131.     /* Parse the effective address */
  132.     p = opParse(op, &memOp, &status);
  133.     NEWERROR(*errorPtr, status);
  134.     if (status < ERROR && *p == ',') {
  135.         /* Check the legality of the addressing mode */
  136.         if (memOp.mode & SourceModes) {
  137.             /* Parse the register list */
  138.             status = OK;
  139.             p = evalList(++p, ®List, &status);
  140.             if (status == OK) {
  141.                 /* Everything's OK, now build the instruction */
  142.  
  143.                 if (pass2) {
  144.                     output((long) (instMask | 0x0400 | effAddr(&memOp)), WORD);
  145.                     loc += 2;
  146.                     output((long) (regList), WORD);
  147.                     loc += 2;
  148.                     }
  149.                 else
  150.                     loc += 4;
  151.                 extWords(&memOp, size, errorPtr);
  152.                 return NORMAL;
  153.                 }
  154.             }
  155.         else {
  156.             NEWERROR(*errorPtr, INV_ADDR_MODE);
  157.             return NORMAL;
  158.             }
  159.         }
  160.  
  161.     /* If the instruction isn't of either form, then return an error */
  162.     NEWERROR(*errorPtr, status);
  163.  
  164.     return NORMAL;
  165.  
  166. }
  167.  
  168.  
  169. int    reg(size, label, op, errorPtr)
  170. int size;
  171. char *label, *op;
  172. int *errorPtr;
  173. {
  174. int    status;
  175. symbolDef *symbol;
  176. unsigned short regList;
  177.  
  178.     if (size)
  179.         NEWERROR(*errorPtr, INV_SIZE_CODE);
  180.     if (!*op) {
  181.         NEWERROR(*errorPtr, SYNTAX);
  182.         return NORMAL;
  183.         }
  184.     op = evalList(op, ®List, errorPtr);
  185.     if (*errorPtr < SEVERE)
  186.         if (!*label) {
  187.             NEWERROR(*errorPtr, LABEL_REQUIRED);
  188.             }
  189.         else {
  190.             status = OK;    
  191.             symbol = define(label, (long) regList, pass2, &status);
  192.             NEWERROR(*errorPtr, status);
  193.             if (status < ERROR)
  194.                 symbol->flags |= REG_LIST_SYM;
  195.             }
  196.  
  197.     return NORMAL;
  198.  
  199. }
  200.  
  201.  
  202. /* Define a couple of useful tests */
  203.  
  204. #define isTerm(c)   (c == ',' || c == '/' || c == '-' || isspace(c) || !c)
  205. #define isRegNum(c) ((c >= '0') && (c <= '7'))
  206.  
  207.  
  208.  
  209. char *evalList(p, listPtr, errorPtr)
  210. char *p;
  211. unsigned short *listPtr;
  212. int *errorPtr;
  213. {
  214. char reg1, reg2, r;
  215. unsigned short regList;
  216. char symName[SIGCHARS+1];
  217. char i;
  218. symbolDef *symbol, *lookup();
  219. int status;
  220.  
  221.     regList = 0;
  222.     /* Check whether the register list is specified
  223.        explicitly or as a register list symbol */
  224.     if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1]) && isTerm(p[2])) {
  225.         /* Assume it's explicit */
  226.         while (TRUE) {    /* Loop will be exited via return */
  227.             if ((p[0] == 'A' || p[0] == 'D') && isRegNum(p[1])) {
  228.                 if (p[0] == 'A')
  229.                     reg1 = (char)(8) + p[1] - '0';
  230.                 else
  231.                     reg1 = p[1] - '0';
  232.                 if (p[2] == '/') {
  233.                     /* Set the bit the for a single register */
  234.                     regList |= (1 << reg1);
  235.                     p += 3;
  236.                     }
  237.                 else if (p[2] == '-')
  238.                     if ((p[3] == 'A' || p[3] == 'D') && isRegNum(p[4]) && isTerm(p[5])) {
  239.                         if (p[5] == '-') {
  240.                             NEWERROR(*errorPtr, SYNTAX);
  241.                             return NULL;
  242.                             }
  243.                         if (p[3] == 'A')
  244.                             reg2 = (char)(8) + p[4] - '0';
  245.                         else
  246.                             reg2 = p[4] - '0';
  247.                         /* Set all the bits corresponding to registers 
  248.                            in the specified range */
  249.                         if (reg1 < reg2)
  250.                             for (r = reg1; r <= reg2; r++)
  251.                                 regList |= (1 << r);
  252.                         else
  253.                             for (r = reg2; r <= reg1; r++)
  254.                                 regList |= (1 << r);
  255.                         if (p[5] != '/') {
  256.                             /* End of register list found - return its value */
  257.                             *listPtr = regList;
  258.                             return p+5;
  259.                             }
  260.                         p += 6;
  261.                         }
  262.                     else {
  263.                         /* Invalid character found - return the error */
  264.                         NEWERROR(*errorPtr, SYNTAX);
  265.                         return NULL;
  266.                         }
  267.                 else {
  268.                     /* Set the bit the for a single register */
  269.                     regList |= (1 << reg1);
  270.                     /* End of register list found - return its value */
  271.                     *listPtr = regList;
  272.                     return p+2;
  273.                     }
  274.                 }
  275.             else {
  276.                 /* Invalid character found - return the error */
  277.  
  278.                 NEWERROR(*errorPtr, SYNTAX);
  279.                 return NULL;
  280.                 }
  281.             }
  282.         }
  283.     else {
  284.         /* Try looking in the symbol table for a register list symbol */
  285.  
  286.         if (!isalpha(*p) && *p != '.') {
  287.             NEWERROR(*errorPtr, SYNTAX);
  288.             return NULL;
  289.             }
  290.         i = 0;
  291.         /* Collect characters of the symbol's name
  292.            (only SIGCHARS characters are significant) */
  293.         do {
  294.             if (i < SIGCHARS)
  295.                 symName[i++] = *p;
  296.             p++;
  297.         } while (isalnum(*p) || *p == '.' || *p == '_' || *p == '$');
  298.         /* Check for invalid syntax */
  299.         if (!isspace(*p) && *p != ',' && *p) {
  300.             NEWERROR(*errorPtr, SYNTAX);
  301.             return NULL;
  302.             }
  303.         symName[i] = '\0';
  304.         /* Look up the name in the symbol table, resulting
  305.            in a pointer to the symbol table entry */
  306.         status = OK;
  307.         symbol = lookup(symName, FALSE, &status);
  308.         if (status < SEVERE)
  309.             /* The register list symbol must be
  310.                previously defined in the program */
  311.             if (status == UNDEFINED) {
  312.                 NEWERROR(*errorPtr, status);
  313.                 }
  314.             else if (pass2 && !(symbol->flags & BACKREF)) {
  315.                 NEWERROR(*errorPtr, REG_LIST_UNDEF);
  316.                 }
  317.             else {
  318.                 if (symbol->flags & REG_LIST_SYM)
  319.                     *listPtr = (unsigned short)symbol->value;
  320.                 else {
  321.                     NEWERROR(*errorPtr, NOT_REG_LIST);
  322.                     *listPtr = 0x1234;
  323.                     }
  324.                 }
  325.         else {
  326.             NEWERROR(*errorPtr, status);
  327.             *listPtr = 0;
  328.             }
  329.         return p;
  330.         }
  331.  
  332.     return NORMAL;
  333.  
  334. }
  335.  
  336.